package cn.edu.zzuli.message.news.service;



import cn.edu.zzuli.message.config.WebMessageDecoder;
import cn.edu.zzuli.message.config.WebSocketCustomEncoding;
import cn.edu.zzuli.message.news.mapper.OfflineMessageMapper;
import cn.edu.zzuli.model.entity.WebMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;

//websocket实现在线消息通知
@ServerEndpoint(value = "/websocket/{userno}",decoders = WebMessageDecoder.class,
        encoders = WebSocketCustomEncoding.class)
@Component
@Slf4j
public class WebSocket {
    //静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;
    //concurrent包的线程安全Set，存放每个客户端对应的MyWebSocket对象
    private static ConcurrentHashMap<String, WebSocket> webSocketSet = new ConcurrentHashMap<String, WebSocket>();
    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;


    //当前发消息的人员编号
    private String userNo = "";


    private static SendServiceImpl sendServiceImpl;
    @Autowired
    public void setUserService(SendServiceImpl sendServiceImpl){
        //通过静态注入
        WebSocket.sendServiceImpl = sendServiceImpl;
    }

    private static OfflineMessageMapper offlineMessageMapper;
    @Autowired
    public void setUserService(OfflineMessageMapper offlineMessageMapper){
        //通过静态注入
        WebSocket.offlineMessageMapper = offlineMessageMapper;
    }

    /**
     * 连接建立成功调用的方法
     * @param session 可选参数。session为与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    @OnOpen
    public void onOpen(@PathParam(value = "userno") String param, Session session, EndpointConfig config) {
        userNo = param;//接收到发送消息的人员编号
        this.session = session;
        webSocketSet.put(param, this);//加入map中
        addOnlineCount();//在线加1
        System.out.println(userNo + "用户登录！当前在线人数为:" + getOnlineCount());
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        if (!userNo.equals("")) {
            webSocketSet.remove(userNo); //从set中删除
            subOnlineCount();//在线减1
            System.out.println(userNo + "用户退出当前在线人数为" + getOnlineCount());
        }
    }

    /**
     * 收到客户端消息后调用
     * @param message 客户端发送过来的消息
     * @param session 可选的参数
     */
    @OnMessage
    public void onMessage(WebMessage message, Session session) {
        System.out.println("userNo:" + userNo);
        System.out.println("来自客户端的消息:" + message);
        System.out.println(message);
    }

    /**
     * 给指定的人发送消息
     * @param message
     */
    public void sendToUser(WebMessage message, Integer type, Integer id, Integer uid) {
        String sendUserNo =  Integer.toString(message.getUserNo());
        String now = getNowTime();
        message.setDate(now);
        try {
            if (webSocketSet.get(sendUserNo) != null) {
                webSocketSet.get(sendUserNo).sendMessage(message);
                System.out.println("消息发送了 : " + message);
            } else {
                System.out.println("当前用户不在线");
                System.out.println("使用微信服务同时存入数据库~");
                // 1:接单 2:取消 3:审核
                if(type == 1){
                    //跑腿通知
                    sendServiceImpl.sendTakeMessage(id,uid);
                    System.out.println("跑腿");
                }else if(type == 2){
                    //订单取消
                    sendServiceImpl.sendCancelMessage(id);
                    System.out.println("取消");
                }else{
                    //审核通知
                    sendServiceImpl.sendApplyMessage(id,uid);
                    System.out.println("审核");
                }

            }
            offlineMessageMapper.insert(message);
            log.info("增加 {} 完成",message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 给所有人发消息
     * @param message
     */
    public void sendAll(WebMessage message,String uid) {
        System.out.println("发送广播消息" + message);
        String now = getNowTime();
        message.setDate(now);
        message.setRadio(1);
        //遍历HashMap
        for (String key : webSocketSet.keySet()) {
            try {
                //判断接收用户是否是当前发消息的用户
                //if (!uid.equals(key)) {
                    webSocketSet.get(key).sendMessage(message);
                    //System.out.println("key = " + key);
                //}
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 给指定的人发送离线的消息
     * @param message
     */
    public void sendOffLineMessageToUser(WebMessage message) {
        String sendUserNo =  Integer.toString(message.getUserNo());
        String now = getNowTime();
        message.setDate(now);
        System.out.println(message);
        if (webSocketSet.get(sendUserNo) != null) {
            try {
                webSocketSet.get(sendUserNo).sendMessage(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println("消息发送了 : " + message);
        } else {
            log.info("出现错误");
        }
    }


    /**
     * 获取当前时间
     * @return 获取现在时间
     */
    private static String getNowTime() {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String format = sdf.format(date);
        return format;
    }
    /**
     * 发生错误时调用
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("错误");
        error.printStackTrace();
    }

    /**
     *发送对象信息调用的方法
     * @param message
     * @throws IOException
     */
    public void sendMessage(WebMessage message) throws IOException {
        try {
            this.session.getBasicRemote().sendObject(message);
        } catch (EncodeException e) {
            e.printStackTrace();
        }
        //this.session.getAsyncRemote().sendText(message);
    }

    /**
     *发送字符串信息调用的方法
     * @param message
     * @throws IOException
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
        //this.session.getAsyncRemote().sendText(message);
    }

    public static synchronized int getOnlineCount() {
        //在线人数
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        //增加
        WebSocket.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        //减少
        WebSocket.onlineCount--;
    }


}